#include "character_device_driver_led.h"

/*
    MMU全称叫做memory manage unit 也就是内存管理单元。在老版本的linux中要求处理器必须有MMU,
    但是现在linux内核已经支持无MMU的处理器了。
    MMU主要完成的功能如下：
    1、完成虚拟空间到物理空间的映射。
    2、内存保护，设置存储器的访问权限，设置虚拟存储空间的缓冲特性。
    物理内存和虚拟内存之间的转换，需要用到两个函数：ioremap和iounmap
*/

#ifdef CHARACTER_DEVICE

static int led_init(device_t dev)
{   
    struct led_user_register_ops * ops = dev->user_data;
    ops->init();
    return 0;
}

static int led_open(device_t dev, int oflag)
{
    return 0;
}

static int led_close(device_t dev)
{
    return 0;
}

static int led_read(device_t dev, int pos, void *buffer, int size)
{   

    return 0;
}

static int led_write(device_t dev, const int pos, const void *buffer, int size)
{   
    struct led_user_register_ops * ops = dev->user_data;
    int *on_off = buffer;
    switch(pos)
    {
        case HAL_LED_RED: 
        case HAL_LED_BLUE:
        case HAL_LED_GREEN:
            if(*on_off == 1)
            {   
                ops->led_on(pos);
            }
            else
            {   
                ops->led_off(pos);
            }
            break;
        default:
            break;
    }
    return 0;
}
static int led_control(device_t dev, int cmd, void *args)
{
    return 0;
}
static struct  device_ops led_ops = {
.init = led_init,
.open = led_open,
.close = led_close,
.read = led_read,
.write = led_write,
.control = led_control,
};
static struct device led_dev = {
    .ops = &led_ops,
};

device_t get_led_device(void)
{
    return &led_dev;
}

void register_led_device(const char *name ,struct led_user_register_ops *ops)
{   
    strncpy(get_led_device()->parent.name,name,strlen(name));
    get_led_device()->user_data = ops;
    get_led_device()->ops->init(get_led_device());
}



int led_demo_init(void)
{
    ql_gpio_init(FT_GOIO_LED_BLUE_PIN, PIN_DIRECTION_OUT, PIN_PULL_DISABLE, PIN_LEVEL_LOW);
    ql_gpio_init(FT_GOIO_LED_GREEN_PIN, PIN_DIRECTION_OUT, PIN_PULL_DISABLE, PIN_LEVEL_LOW);
    ql_gpio_init(FT_GOIO_LED_RED_PIN, PIN_DIRECTION_OUT, PIN_PULL_DISABLE, PIN_LEVEL_LOW);
}
int led_demo_on(enum led_color color)
{  
    switch(color)
    {   
        case HAL_LED_RED:
            wHal_LED_ctrl(LED_RED, LED_LEVEL_1);
            wHal_LED_ctrl(LED_BLUE|LED_GREEN, LED_LEVEL_0);
            break;
        case HAL_LED_BLUE:
            wHal_LED_ctrl(LED_BLUE, LED_LEVEL_1);
            wHal_LED_ctrl(LED_RED|LED_GREEN, LED_LEVEL_0);
            break;
        case HAL_LED_GREEN:
            wHal_LED_ctrl(LED_GREEN, LED_LEVEL_1);
            wHal_LED_ctrl(LED_BLUE|LED_RED, LED_LEVEL_0);
            break;
        default:
            break;
    }
}
static struct led_user_register_ops ops = {
        .init = led_demo_init,
        .led_on = led_demo_on,
    };
void led_demo(void)
{   
    int on = 1;
    register_led_device("led" ,&ops);
    led_open(get_led_device(),0);
    led_write(get_led_device(),HAL_LED_GREEN,&on,sizeof(int));
}
#endif

#ifdef LINUX_CHARACTER_DEVICE





#endif